昨天我們把 Skill 的觸發條件、進入點、意圖三問與反蒙蔽協議定了下來。那些都還在「審查真正開始之前」的準備動作。
今天進入 Phase 2:把能交給確定性工具的部分交出去。
確定性工具的價值不只在省下 LLM token。它們會留下可重播、可比較的輸出,讓後面的判斷有證據可查。
有些工具早已存在,只是輸出不適合直接閱讀。AI 的角色不是取代掃描器,而是整理證據、協助逐筆判讀。
因此,我把 Phase 2 定調為靜態工具掃描,目前納入以下工具:
專案主要使用 Python 與 JavaScript,因此先納入:
這兩個工具 ruff、ty 都是 Astral 推出的。以下用 uv 安裝到持久的工具環境;若只想執行一次,也可以改用 uvx ruff check 或 uvx ty check。
# On macOS and Linux.
curl -LsSf https://astral.sh/uv/install.sh | sh
uv tool install ruff
測試
ruff check
uv tool install ty
測試
ty check
npm install -g oxlint
測試
oxlint --version
選到的這些工具都是 Rust 寫的唷 😂
截至 2026 年 8 月,Rust 在 TIOBE Index 排名第 10,恭喜 Rust 進入前十!🎉
先講為什麼這條軌道非有不可。
下面這組數字來自 Zero Day Clock,該站把 TTE(time-to-exploit)定義為 CVE 公開到第一個已知可用 exploit 出現的時間。資料來源混合 CISA KEV、ExploitDB、Metasploit、Nuclei、PoC-in-GitHub 等十個來源,所以它量的是 exploit availability,不完全等於漏洞已在真實環境中遭到攻擊。
以下是我在 2026 年 8 月 12 日查到的快照。每年只統計該資料集收錄、已有已知 exploit 的 CVE,不是當年所有公開漏洞。
| 年份 | 樣本數 | 中位數 | 平均 |
|---|---|---|---|
| 2018 | 273 | 771 天 | 830 天 |
| 2019 | 295 | 485 天 | 613 天 |
| 2020 | 359 | 231 天 | 487 天 |
| 2021 | 486 | 68 天 | 304 天 |
| 2022 | 450 | 68 天 | 263 天 |
| 2023 | 505 | 5.3 天 | 127 天 |
| 2024 | 620 | 0.5 天 | 53 天 |
| 2025 | 483 | 0 天 | 21 天 |
這張表不能直接告訴每個團隊的修補期限:它沒有納入資產是否暴露、利用前提、補丁何時可用或既有控制。不過它足以提醒我,不該再假設 exploit 通常會在漏洞公開很久以後才出現。
2026 年尚未結束,當年度數字還會持續變動,也有未完年度的選樣偏差,因此我不把它放進表格或拿來下結論。
如果你在網站上看到 2026 年的 TTE 中位數是負數,負號的意思是:資料記錄的第一個已知 exploit,早於 CVE 的公開時間。Zero Day Clock 也把
TTE ≤ 0歸類為 zero-day。這不等於每一個 2026 年漏洞都在公開前遭到攻擊,也不一定代表已在真實環境中被利用;資料來源仍混合 exploit 與 PoC 紀錄。
基於這個風險訊號,我的流程選擇在每次 review 都重新掃描,再依暴露面、可達性與組織政策決定處理優先序,而不是只等季度盤點。
而這件事跟 AI 寫 code 直接相關。你請它加一個功能,它可能很自然地把需要的套件裝進來,pyproject.toml 或 package.json 就多了幾行。除非流程明確接上掃描工具與組織政策,不能假設 AI 會主動檢查依賴漏洞,或正確套用 High 以上的處置規則。
Trivy 先產生已知弱點候選;它不會自動證明我的程式路徑真的可達、設定符合,或攻擊前提成立。AI Agent 與人接著要查使用版本、受影響 API、呼叫路徑、設定與攻擊前提,才能把候選分成「條件待確認」「已證實可達」或「已證實不可達」。
在其他條件相近時,已證實可達的 High 可能比目前不可達的 Critical 更值得先處理;最終仍要結合資產、暴露面、攻擊前提與組織 SLA。
參考官方文件
macOS 或已安裝 Homebrew 的 Linux 可以直接使用:
brew install trivy
trivy --version
其他環境請依 官方安裝文件 或 GitHub Releases 選擇對應套件;需要可重現環境時,應固定已驗證的版本與 checksum,而不是在文章中硬寫一個日後會過期的「最新版」。
沒有 Homebrew 時,Trivy 官方文件也提供以下安裝方式:
curl -sfL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/install.sh | sudo sh -s -- -b /usr/local/bin v0.73.0
trivy --version
這條指令會把遠端腳本交給具有系統權限的 shell。執行前應先下載並檢視腳本;正式或可重現環境還要核對 v0.73.0 release 提供的 checksum。文中的 v0.73.0 是 2026 年 8 月 12 日查核時的版本,不代表永遠是最新版。
trivy image --download-db-only
trivy fs \
--scanners vuln,misconfig,secret \
--severity CRITICAL,HIGH,MEDIUM \
--format json \
--output "{artifact_path}" \
{project_root}
眼尖的讀者會發現
--scanners裡帶了secrettrivy 一次呼叫可以同時掃漏洞、設定檔錯誤與憑證洩漏。這也是一個刻意的取捨:市面上有專門掃 git 歷史憑證的工具(如
gitleaks),但對本系列的目標而言,trivy 兼任的 secret 掃描已覆蓋工作目錄這一層,我就不再多引入一個工具、多一份安裝與維護成本。若你的情境需要回溯整段 git 歷史裡曾經 commit 過又刪掉的憑證,再考慮補上專門工具。
我曾在一場真實審查裡發現,這條軌道差點變成「假裝有跑」。那場審查跑在限制網路的容器裡,git clone 被防火牆擋下,skill 改用 GitLab 的 compare API 重建程式碼樹:重建只抓得到原始碼,根目錄的 pyproject.toml 跟 uv.lock 都不在。Trivy 對著一棵沒有任何依賴 manifest 的樹照樣 exit 0,吐出空報告,差一點就被寫成「安全掃描零命中」。事後用 SSH clone 把完整的樹拿回來重掃,才出現多筆 High 與 Medium 弱點。「無標的」與「乾淨」是兩件事。
修法是讓 scan_runner 在掃描後檢查樹裡有沒有已知的依賴 manifest/lockfile,例如 pyproject.toml、uv.lock、requirements.txt、package.json、package-lock.json、pnpm-lock.yaml 或 yarn.lock。一個都沒有,就在結果裡強制標明「vuln 掃描沒有標的,零發現不代表依賴乾淨」,報告也必須轉述。上面的 TTE 資料講的是這條軌道為什麼值得建立;這次事故補上另一半:它看起來有跑、實際沒東西可掃,比沒跑更危險。
SAST(靜態應用程式安全測試,Static Application Security Testing)
SAST 不執行程式碼,而是分析原始碼,找出可能的安全弱點;它屬於白箱測試的一種。
我評估過 Semgrep。後來因為產品與授權界線有所變化(背景可參考這篇整理),最後選用它的開源 fork:Opengrep。
Opengrep 官方宣稱相容 Semgrep 規則語法,但引擎相容不代表規則授權也自動相容。實際使用時仍要固定 ruleset 的來源與版本,並逐一確認授權;公開範例則使用自有的最小規則。
直接到 Opengrep Releases 下載符合作業系統與 CPU 架構的預編譯執行檔。以 macOS/Linux 為例,下載後重新命名並放進 PATH:
mv opengrep_<platform>_<arch> opengrep # 重新命名
chmod +x opengrep # 加上執行權限
sudo mv opengrep /usr/local/bin/ # 移到 PATH 內的目錄
opengrep --version # 確認安裝結果
例如 release 內可見 opengrep_osx_arm64、opengrep_manylinux_x86 與 Windows .exe;不要把 <platform>、<arch> 原樣照抄。正式環境建議一併驗證 release 提供的 .sig 與 .cert。
以上工具輸出的結果只是待驗證線索。AI Agent 要逐條查回程式碼與執行條件,確認後才能呈現在報告中。
若工具沒有任何發現,至少要檢查三件事:exit code、預期輸入與實際掃描標的,以及結果結構/coverage。任一項不足,都只能標記為無效或無法判定,不能寫成「零命中」。Trivy 預設即使找到問題也可能 exit 0,因此 exit code 本身更不能代替結果解析。
這些軌道彼此沒有資料相依,因此我讓它們在資源受控、output 分離,而且資料庫已準備完成的前提下並行;環境資源不足時則改為依序執行。
今天替 code review 鋪了幾條確定性工具的軌道:Ruff、ty 與 Oxlint 處理格式、型別與 lint,Trivy 找依賴、設定與憑證問題,Opengrep 則負責 SAST。工具先產生可重播的原始證據,AI Agent 與人再回到程式碼與執行條件逐筆判讀。
更重要的是,指令成功結束與報告零發現,都不等於審查有效。只有在輸入完整、確實存在掃描標的,而且結果結構與 coverage 合理時,零發現才有資格被解讀為乾淨;否則只能標記為無效或無法判定。
後面還有 Phase 3:深度審查 還有 Phase 4:報告交付與發佈,就留給接下來幾天接力吧 🎉!